package com.example.service;

import com.example.entity.ChatGroup;
import com.example.entity.ChatInfo;
import com.example.mapper.ChatGroupMapper;
import com.example.mapper.ChatInfoMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket服务
 */
@ServerEndpoint(value = "/chatServer/{userId}")
@Component
public class WebSocketServer {
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    @Resource
    private ChatGroupMapper chatGroupMapper;

    /**
     * 记录当前在线连接数
     */
    public static final Map<Integer, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     * 当WebSocket连接成功时，此方法会被调用，用于处理新用户的连接请求
     *
     * @param session 用户的会话对象，用于后续的通信
     * @param userId  用户ID，用于唯一标识每个用户
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Integer userId) {
        // 将用户ID与会话对象映射并存储到sessionMap中，以便后续通过用户ID查找会话
        sessionMap.put(userId, session);
        // 记录日志，输出新用户加入的信息及当前在线用户数量
        log.info("有新用户加入，userId={}, 当前在线人数为：{}", userId, sessionMap.size());
    }


    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("userId") Integer userId) {
        sessionMap.remove(userId);
        log.info("有一连接关闭，移除userId={}的用户session, 当前在线人数为：{}", userId, sessionMap.size());
    }

    /**
     * 收到客户端消息后调用的方法
     * 此方法作为后台接收客户端发送的消息的入口，负责处理来自客户端的json数据
     * 它遍历所有已建立的会话，将接收到的消息广播回所有客户端
     * 主要作用是实现消息的中转，确保所有连接的客户端都能接收到相同的消息
     *
     * @param message 客户端发送的json数据字符串
     */
    @OnMessage
    public void onMessage(String message) {
        // 遍历所有已建立的会话
        for (Session session : sessionMap.values()) {
            // 记录服务端向客户端发送的消息内容
            log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
            try {
                // 向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                // 记录发送消息时的错误信息
                log.error("Socket发送消息失败", e);
            }
        }
    }


    @OnError
    public void onError(Session session, Throwable error) {
        log.error("Socket错误", error);
    }
}